package io.github.junxworks.qt.modules.mm.engine;

import org.apache.commons.beanutils.ConvertUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import io.github.junxworks.ep.qlexp.ExecResult;
import io.github.junxworks.ep.qlexp.RuleEngine;
import io.github.junxworks.ep.qlexp.SpringQLContext;
import io.github.junxworks.ep.sys.constants.YesNo;
import io.github.junxworks.junx.core.exception.BaseRuntimeException;
import io.github.junxworks.junx.core.util.ExceptionUtils;
import io.github.junxworks.junx.core.util.StringUtils;
import io.github.junxworks.qt.constants.FieldType;
import io.github.junxworks.qt.modules.mm.vo.FieldVo;

/**
 * 字段校验
 *
 * @ClassName:  FieldChecker
 * @author: 王兴
 * @date:   2019-11-25 14:24:14
 * @since:  v1.0
 */
@Component
public class Fielder {

	@Autowired
	private RuleEngine engine;

	private static final String FIELD_NAME = "参数值";

	/**
	 * 校验字段信息
	 *
	 * @param fields the fields
	 * @param inputParams the input params
	 * @return the list
	 */
	public Object translateField(String dsName, FieldVo f, Object dataObj) {
		String innerCName = f.getInnerCName();
		Object handledValue = null;
		if (dataObj == null) {
			//【1】非空判断
			if (YesNo.YES.getValue() == f.getNotNull()) {
				throw new BaseRuntimeException("参数值为空");
			}
		} else {
			FieldType externalType = FieldType.getEnum(f.getExternalType());
			if (externalType == null) {
				throw new BaseRuntimeException("没有找到有效的外部字段类型[%s]", f.getExternalType());
			}
			Class<?> eType = externalType.getClazz();
			try {
				//【2】外部类型转换
				handledValue = ConvertUtils.convert(dataObj, eType);
			} catch (Exception e) {
				throw new BaseRuntimeException("外部输入值类型转换失败，失败原因：%s", ExceptionUtils.getCauseMessage(e));
			}
		}
		if (YesNo.YES.getValue() == f.getCheckValue()) {
			//【3】入参校验
			String checkExp = f.getCheckExp(); //值校验表达式
			if (StringUtils.isNull(checkExp)) {
				throw new BaseRuntimeException("开启了输入字段值校验，但是校验表达式为空");
			}
			SpringQLContext qlCtx = new SpringQLContext();
			qlCtx.put(FIELD_NAME, handledValue);
			ExecResult execRes = null;
			try {
				execRes = engine.execute(checkExp, qlCtx);
				if (!execRes.isSuccess()) {
					throw new BaseRuntimeException(execRes.getErrorMsg());
				}
			} catch (Exception e) {
				throw new BaseRuntimeException("执行值校验表达式失败，失败原因：%s", ExceptionUtils.getCauseMessage(e));
			}
			if (execRes.getResult() == null) {
				throw new BaseRuntimeException("内部字段[%s]开启了输入字段值校验，但是校验表达式返回值不是布尔类型", innerCName);
			}
			boolean pass = true;
			try {
				pass = Boolean.valueOf(execRes.getResult().toString());
			} catch (Exception e) {
				throw new BaseRuntimeException("校验表达式返回值不是布尔类型");
			}
			if (!pass) {
				throw new BaseRuntimeException("外部输入值校验不通过，外部输入值为[%s]", String.valueOf(dataObj));
			}
		}
		//【4】内部值转换 
		String transExp = f.getTransExp(); //通过表达式转值
		if (StringUtils.notNull(transExp)) {
			SpringQLContext qlCtx = new SpringQLContext();
			qlCtx.put(FIELD_NAME, handledValue);
			ExecResult execRes = null;
			try {
				execRes = engine.execute(transExp, qlCtx);
				if (!execRes.isSuccess()) {
					throw new BaseRuntimeException(execRes.getErrorMsg());
				}
			} catch (Exception e) {
				throw new BaseRuntimeException("执行值转换表达式失败，失败原因：%s", ExceptionUtils.getCauseMessage(e));
			}
			if (execRes.getResult() == null) {
				throw new BaseRuntimeException("字段值转换表达式返回值为空");
			}
			handledValue = execRes.getResult();
		}
		//【5】内部类型转换
		if (handledValue != null) {
			FieldType innerType = FieldType.getEnum(f.getInnerType());
			if (innerType == null) {
				throw new BaseRuntimeException("没有找到有效的内部字段类型[%s]", f.getInnerType());
			}
			Class<?> iType = innerType.getClazz();
			if (iType != handledValue.getClass()) {
				//如果内部类型和当前值类型不一致
				try {
					handledValue = ConvertUtils.convert(handledValue, iType);
				} catch (Exception e) {
					throw new BaseRuntimeException("内部类型转换失败，失败原因：%s", ExceptionUtils.getCauseMessage(e));
				}
			}
		}
		//【6】返回处理后的值
		return handledValue;
	}
}
